Problem antialiasingem

Otázka od: Michal Adler

30. 11. 2003 11:07

Zdravim vsechny,
potreboval bych poradit od nekoho kdo dela(l) nekdy neco s grafikou v
Delphi.

Potrebuji z obrazku udelat jeho zmenseninu v nejakem pomeru treba 1:2
(tohle neni problem). Prepocitat velikost bitmapy a ulozit ji umim.
Problem je, ze ty vysledne obrazky jsou takove kostrbate proste
nevypadaji tak dobre jako kdyz si je zmensim treba ve photoshopu nebo
jinem programu. Potrebuji tedy dodelat neco jako "vyhlazovani"
vysledne grafiky.

Pokud nekdo vite jak na to, nebo vite o nejake free komponente, ktera
tohle zvladne budu strasne vdecnej. Uplne nejlepsi by byl nejaky
utrzek kodu do mailu...  

predem moc dekuji
Michal Adler



Odpovedá: Vaclav Sazima

30. 11. 2003 15:28

 Ahoj,
pod NT,2000,XP jednoduse :

       SetStretchBltMode(Image.Picture.Bitmap.Canvas.Handle, HALFTONE);
       StretchOK := StretchBlt(Image.Picture.Bitmap.Canvas.Handle....

Pod win9x je treba to zajistit samostatne, casto to je soucasti ruznych
grafickych knihoven, napr. Envision library, hledej treba slovo
bilinear. Jinak filtru, ktere odstranuji zubatost, je rada a vysledky se
lisi podle toho, co je na puvodnim obrazku.

  Vaclav Sazima

Michal Adler wrote:
> Potrebuji z obrazku udelat jeho zmenseninu v nejakem pomeru treba 1:2
> (tohle neni problem). Prepocitat velikost bitmapy a ulozit ji umim.
> Problem je, ze ty vysledne obrazky jsou takove kostrbate proste
> nevypadaji tak dobre jako kdyz si je zmensim treba ve photoshopu nebo
> jinem programu. Potrebuji tedy dodelat neco jako "vyhlazovani"
> vysledne grafiky.


Odpovedá: Ondrej

30. 11. 2003 20:15

mozem ti poslat aj cely program, ak mi povies kde. inak tu je presne to co
potrebujes. je to vypis programu, nie vseobecny unit:


unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls, ExtCtrls, Buttons;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Image3: TImage;
    Button3: TButton;
    Button4: TButton;
    ScrollBox1: TScrollBox;
    Image2: TImage;
    ScrollBox2: TScrollBox;
    Image1: TImage;
    BitBtn1: TBitBtn;
    Label1: TLabel;
    Label2: TLabel;
    CheckBox1: TCheckBox;
    procedure Button2Click(Sender: TObject);
    procedure Button1Click(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

  type
  pRGBArray = ^TRGBArray;
  TRGBArray = ARRAY[0..high(smallint)] OF TRGBTriple;




var
  Form1: TForm1;
  zoom:boolean=false;

const z=3;

implementation

{$R *.DFM}

procedure TForm1.Button2Click(Sender: TObject);
begin
Close;
end;

procedure FastAntiAlias;
 var
  x, y, j,i, totr, totg, totb: integer;
  big_bmp, out_bmp : TBitmap;
  cx, cy : integer;
  Row1, Row2, Row3, DestRow: pRGBArray;
  sirka,vyska:integer;
begin
{omlouvam se za dlouhou proceduru, ale to jinak udelat neslo
 je to proste rutina, ktera se neda volat od nikud jinud}
 sirka:=form1.Image1.Width;
 vyska:=form1.Image1.Height;

  // vytvoreni pomocne bitmapy k presamplovani do vyssiho rozliseni
  big_bmp := TBitmap.Create;
  big_bmp.Width := sirka*z;
  big_bmp.Height := vyska*z;
  big_bmp.PixelFormat := pf24bit;
  big_bmp.Canvas.Draw(0,0,form1.image3.Picture.Bitmap);

 file://Vytvoreni vystupni bitmapy
  out_bmp := TBitmap.Create;
  out_bmp.Width := sirka;
  out_bmp.Height := vyska;
  out_bmp.PixelFormat := pf24bit;


 // pro vsechny radky
  for y := 0 to vyska - 1 do
  begin
      // spocitam vzorek 3 x 3 pixels
    cy := y*z;
    // Vezmu body od aktualniho, predchziho a nasledujYcYho sloupce v
presamplovane bitmape
    Row1 := big_bmp.ScanLine[cy];
    Row2 := big_bmp.ScanLine[cy+1];
    Row3 := big_bmp.ScanLine[cy+2];

    // Vezmu ukazatel na sloupec y
    DestRow := out_bmp.ScanLine[y];

    file://pro vsechny radky
        for x := 0 to sirka - 1 do
    begin
      // zpracuju vzorky z 3 x 3 pixelu
      cx := x*z;

      // icializace vysledne barvy
      totr := 0;
      totg := 0;
      totb := 0;

      // Pro vsechny pxely ve vzorku
      for i:=0 to 2 do
      begin
        // nova hodnota cervene
        totr := totr + Row1[cx + i].rgbtRed
             + Row2[cx + i].rgbtRed
             + Row3[cx + i].rgbtRed;
        // nova hodnota zelene
        totg := totg + Row1[cx + i].rgbtGreen
             + Row2[cx + i].rgbtGreen
             + Row3[cx + i].rgbtGreen;
        // nova hodnota modre
        totb := totb + Row1[cx + i].rgbtBlue
             + Row2[cx + i].rgbtBlue
             + Row3[cx + i].rgbtBlue;
      end;

      // nastaveni vyslednych pixelu
      DestRow[x].rgbtRed := totr div 9;
      DestRow[x].rgbtGreen := totg div 9;
      DestRow[x].rgbtBlue := totb div 9;
     end;
  end;

  form1.Image2.canvas.Draw(0,0,out_bmp);//zkopirovani vysledne bitmapy
file://uvolneni vsech pomocnych bitmap
big_bmp.free;
out_bmp.free;
End;




procedure SeparateColor(color : TColor; var r, g, b : Integer);
begin
  r := Byte(color);
  g := Byte(color shr 8);
  b := Byte(color shr 16);
end;

procedure AntiAliasing;
var
  x, y: integer;
  totr, totg, totb, r, g, b : integer;
  i, j: integer;
begin
  file://pro vUechny ??dky
  for y := 0 to form1.image1.Height - 1 do
  begin
  Application.ProcessMessages; // nech aplikaci vykreslit se po ?adcYch
    file://pro vUechny sloupce
    for x := 0 to form1.image1.Width - 1 do
    begin
      totr := 0; file://inicializuj barvu
      totg := 0;
      totb := 0;

      // p?eRti barvu ze vUech okolnich pixelu
      for i := 0 to 2 do
      begin
        for j := 0 to 2 do
        begin
          SeparateColor(form1.image3.Canvas.Pixels[(x*z) + j, (y*z) + i], r,
g, b); file://oddyl barevnU so?ky
          totr := totr + r; file://p?iRti p?Yspyvek u ka?dU slo?ky zvlaUL
          totg := totg + g;
          totb := totb + b;
        end;
      end;

      form1.image2.Canvas.Pixels[x,y] := RGB(totr div 9, file://nakresli
vyslednou barvu podylenou 9
                                        totg div 9,
                                        totb div 9);
    end;
  end;
end;


procedure TForm1.Button1Click(Sender: TObject);
var cas:integer;
begin
Image2.Canvas.FillRect(Image2.Canvas.ClipRect);
Application.ProcessMessages;
cas:=GetTickCount;
form1.Enabled:=false;
if CheckBox1.Checked then
FastAntiAlias
else
AntiAliasing;
cas:=GetTickCount-cas;
form1.Enabled:=true;
label2.caption:=floattostr(cas/1000)+'s';
end;

procedure TForm1.FormCreate(Sender: TObject);
begin

image2.Canvas.FillRect(Image2.Canvas.ClipRect);

with image1.canvas do
begin
Pen.Width:=3;
FillRect(Image1.Canvas.ClipRect);
Brush.Color:=clyellow;
Ellipse(1,1,image1.Width-1,Image1.Height-1);
LineTo(image1.Width,image1.Height);
MoveTo(image1.Width,0);
lineto(0,image1.Height);
end;
image1.Canvas.Font.Size := 30;
image1.Canvas.Font.Name := 'Arial';
image1.Canvas.TextOut(10,100,'Ondrej 2003');

image3.width:=image1.Width*z;
image3.Height:=image1.Height*z;
with image3.canvas do
begin
Pen.Width:=3*z;
FillRect(Image3.Canvas.ClipRect);
Brush.Color:=clyellow;
Ellipse(z,z,image3.Width-z,image3.Height-z);
LineTo(image1.Width*z,image1.Height*z);
MoveTo(image1.Width*z,0);
lineto(0,image1.Height*z);
end;
image3.Canvas.Font.Size := 90;
image3.Canvas.Font.Name := 'Arial';
image3.Canvas.TextOut(3*10,3*100,'Ondrej 2003');


end;

procedure TForm1.Button3Click(Sender: TObject);
begin
if not zoom then
begin
Image1.Width:=Image1.Width*3;
Image1.height:=Image1.Height*3;
Image2.Width:=Image2.Width*3;
Image2.height:=Image2.Height*3;
zoom:=true;
end;
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
if zoom then
begin
Image1.Width:=Image1.Width div 3;
Image1.height:=Image1.Height div 3;
Image2.Width:=Image2.Width div 3;
Image2.height:=Image2.Height div 3;
zoom:=false;
end;
end;

end.



----- Original Message -----
From: "Michal Adler" <michal.adler@fotoadler.cz>
To: <delphi-l@clexpert.cz>
Sent: Sunday, November 30, 2003 11:05 AM
Subject: Problem antialiasingem


> Zdravim vsechny,
> potreboval bych poradit od nekoho kdo dela(l) nekdy neco s grafikou v
> Delphi.
>
> Potrebuji z obrazku udelat jeho zmenseninu v nejakem pomeru treba 1:2
> (tohle neni problem). Prepocitat velikost bitmapy a ulozit ji umim.
> Problem je, ze ty vysledne obrazky jsou takove kostrbate proste
> nevypadaji tak dobre jako kdyz si je zmensim treba ve photoshopu nebo
> jinem programu. Potrebuji tedy dodelat neco jako "vyhlazovani"
> vysledne grafiky.
>
> Pokud nekdo vite jak na to, nebo vite o nejake free komponente, ktera
> tohle zvladne budu strasne vdecnej. Uplne nejlepsi by byl nejaky
> utrzek kodu do mailu...  
>
> predem moc dekuji
> Michal Adler
>
>
>
>